use crate::CryptoCommands;
use indicatif::{ProgressBar, ProgressStyle};
use rand::Rng;
use std::fs;
use std::path::Path;
use aes_gcm::{Aes256Gcm, Key, Nonce};
use aes_gcm::aead::{Aead, NewAead};
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use argon2::password_hash::{rand_core::OsRng, SaltString};
use argon2::password_hash::{PasswordHasher as _, PasswordVerifier as _};
use base64::{Engine as _, engine::general_purpose};
use hex;
use md5;
use sha2::{Sha256, Sha512, Digest};
use qrcode::QrCode;
use image::Luma;

pub fn handle_crypto_commands(command: CryptoCommands, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    match command {
        CryptoCommands::Password { length, special, exclude_similar } => {
            generate_password(length, special, exclude_similar, verbose)?;
        },
        CryptoCommands::Hash { file, algorithm } => {
            calculate_hash(&file, &algorithm, verbose)?;
        },
        CryptoCommands::Encrypt { file, output, password, algorithm } => {
            encrypt_file(&file, &output, &password, &algorithm, verbose)?;
        },
        CryptoCommands::Decrypt { file, output, password } => {
            decrypt_file(&file, &output, &password, verbose)?;
        },
        CryptoCommands::Keypair { type_, bits } => {
            generate_keypair(&type_, bits, verbose)?;
        },
    }
    Ok(())
}

fn generate_password(length: usize, special: bool, exclude_similar: bool, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let mut rng = rand::thread_rng();
    let mut charset = String::from("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
    
    if special {
        charset.push_str("!@#$%^&*()_+-=[]{}|;:,.<>?");
    }
    
    if exclude_similar {
        charset = charset.chars()
            .filter(|&c| !"0O1lI".contains(c))
            .collect();
    }
    
    let password: String = (0..length)
        .map(|_| charset.chars().nth(rng.gen_range(0..charset.len())).unwrap())
        .collect();
    
    println!("🔐 生成的密码:");
    println!("  {}", password);
    
    if verbose {
        let entropy = (charset.len() as f64).log2() * length as f64;
        println!("  长度: {} 字符", length);
        println!("  字符集大小: {}", charset.len());
        println!("  熵值: {:.2} 位", entropy);
        println!("  强度: {}", if entropy >= 80.0 { "强" } else if entropy >= 60.0 { "中等" } else { "弱" });
    }
    
    Ok(())
}

fn calculate_hash(file: &Path, algorithm: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("计算哈希值...");
    
    let contents = fs::read(file)?;
    let hash = match algorithm {
        "md5" => {
            let mut hasher = md5::Md5::new();
            hasher.update(&contents);
            format!("{:x}", hasher.finalize())
        },
        "sha1" => {
            let mut hasher = sha1::Sha1::new();
            hasher.update(&contents);
            format!("{:x}", hasher.finalize())
        },
        "sha256" => {
            let mut hasher = Sha256::new();
            hasher.update(&contents);
            format!("{:x}", hasher.finalize())
        },
        "sha512" => {
            let mut hasher = Sha512::new();
            hasher.update(&contents);
            format!("{:x}", hasher.finalize())
        },
        _ => return Err("不支持的哈希算法".into()),
    };
    
    pb.finish_with_message("✅ 哈希计算完成");
    
    println!("🔐 {} 哈希值:", algorithm.to_uppercase());
    println!("  {}", hash);
    
    if verbose {
        println!("  文件: {}", file.display());
        println!("  大小: {} 字节", contents.len());
        println!("  算法: {}", algorithm);
    }
    
    Ok(())
}

fn encrypt_file(file: &Path, output: &Path, password: &str, algorithm: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("加密文件...");
    
    let contents = fs::read(file)?;
    let encrypted = match algorithm {
        "aes256" => {
            let key = derive_key(password, 32)?;
            let cipher = Aes256Gcm::new(Key::from_slice(&key));
            let nonce = generate_nonce();
            cipher.encrypt(&nonce, contents.as_ref())
                .map_err(|_| "加密失败")?
        },
        "aes128" => {
            let key = derive_key(password, 16)?;
            let cipher = Aes256Gcm::new(Key::from_slice(&key));
            let nonce = generate_nonce();
            cipher.encrypt(&nonce, contents.as_ref())
                .map_err(|_| "加密失败")?
        },
        _ => return Err("不支持的加密算法".into()),
    };
    
    // 将 nonce 和加密数据一起保存
    let mut result = Vec::new();
    result.extend_from_slice(&generate_nonce());
    result.extend_from_slice(&encrypted);
    
    fs::write(output, result)?;
    
    pb.finish_with_message("✅ 加密完成");
    
    println!("🔐 文件加密成功:");
    println!("  输入: {}", file.display());
    println!("  输出: {}", output.display());
    println!("  算法: {}", algorithm);
    
    if verbose {
        println!("  原始大小: {} 字节", contents.len());
        println!("  加密后大小: {} 字节", result.len());
    }
    
    Ok(())
}

fn decrypt_file(file: &Path, output: &Path, password: &str, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("解密文件...");
    
    let encrypted_data = fs::read(file)?;
    
    if encrypted_data.len() < 12 {
        return Err("加密文件格式无效".into());
    }
    
    let nonce = &encrypted_data[..12];
    let ciphertext = &encrypted_data[12..];
    
    let key = derive_key(password, 32)?;
    let cipher = Aes256Gcm::new(Key::from_slice(&key));
    
    let decrypted = cipher.decrypt(nonce.into(), ciphertext)
        .map_err(|_| "解密失败，密码可能错误")?;
    
    fs::write(output, decrypted)?;
    
    pb.finish_with_message("✅ 解密完成");
    
    println!("🔓 文件解密成功:");
    println!("  输入: {}", file.display());
    println!("  输出: {}", output.display());
    
    if verbose {
        println!("  加密大小: {} 字节", encrypted_data.len());
        println!("  解密后大小: {} 字节", decrypted.len());
    }
    
    Ok(())
}

fn generate_keypair(type_: &str, bits: usize, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    let pb = ProgressBar::new_spinner();
    pb.set_message("生成密钥对...");
    
    match type_ {
        "rsa" => {
            generate_rsa_keypair(bits, verbose)?;
        },
        "ed25519" => {
            generate_ed25519_keypair(verbose)?;
        },
        _ => return Err("不支持的密钥类型".into()),
    }
    
    pb.finish_with_message("✅ 密钥对生成完成");
    Ok(())
}

fn generate_rsa_keypair(bits: usize, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    use rsa::{RsaPrivateKey, RsaPublicKey};
    use rsa::pkcs8::{EncodePrivateKey, EncodePublicKey};
    
    let mut rng = rand::thread_rng();
    let private_key = RsaPrivateKey::new(&mut rng, bits)?;
    let public_key = RsaPublicKey::from(&private_key);
    
    let private_pem = private_key.to_pkcs8_pem(rsa::pkcs8::LineEnding::LF)?;
    let public_pem = public_key.to_public_key_pem(rsa::pkcs8::LineEnding::LF)?;
    
    fs::write("private_key.pem", private_pem)?;
    fs::write("public_key.pem", public_pem)?;
    
    println!("🔑 RSA 密钥对生成成功:");
    println!("  私钥: private_key.pem");
    println!("  公钥: public_key.pem");
    println!("  位数: {}", bits);
    
    if verbose {
        println!("  私钥格式: PKCS#8 PEM");
        println!("  公钥格式: SPKI PEM");
    }
    
    Ok(())
}

fn generate_ed25519_keypair(verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    use ed25519_dalek::{SigningKey, VerifyingKey};
    use ed25519_dalek::pkcs8::{EncodePrivateKey, EncodePublicKey};
    
    let mut rng = rand::thread_rng();
    let signing_key = SigningKey::generate(&mut rng);
    let verifying_key = VerifyingKey::from(&signing_key);
    
    let private_pem = signing_key.to_pkcs8_pem(ed25519_dalek::pkcs8::LineEnding::LF)?;
    let public_pem = verifying_key.to_public_key_pem(ed25519_dalek::pkcs8::LineEnding::LF)?;
    
    fs::write("ed25519_private.pem", private_pem)?;
    fs::write("ed25519_public.pem", public_pem)?;
    
    println!("🔑 Ed25519 密钥对生成成功:");
    println!("  私钥: ed25519_private.pem");
    println!("  公钥: ed25519_public.pem");
    
    if verbose {
        println!("  私钥格式: PKCS#8 PEM");
        println!("  公钥格式: SPKI PEM");
        println!("  算法: Ed25519");
    }
    
    Ok(())
}

fn derive_key(password: &str, length: usize) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
    let salt = b"salt123456789012"; // 在实际应用中应该使用随机盐
    let mut key = vec![0u8; length];
    
    // 使用 PBKDF2 派生密钥
    use pbkdf2::{pbkdf2_hmac, Algorithm};
    use sha2::Sha256;
    
    pbkdf2_hmac::<Sha256>(password.as_bytes(), salt, 10000, &mut key);
    
    Ok(key)
}

fn generate_nonce() -> [u8; 12] {
    let mut nonce = [0u8; 12];
    rand::thread_rng().fill(&mut nonce);
    nonce
}

// 辅助函数
pub fn hash_password(password: &str) -> Result<String, Box<dyn std::error::Error>> {
    let salt = SaltString::generate(&mut OsRng);
    let argon2 = Argon2::default();
    let password_hash = argon2.hash_password(password.as_bytes(), &salt)?;
    Ok(password_hash.to_string())
}

pub fn verify_password(password: &str, hash: &str) -> Result<bool, Box<dyn std::error::Error>> {
    let parsed_hash = PasswordHash::new(hash)?;
    Ok(Argon2::default().verify_password(password.as_bytes(), &parsed_hash).is_ok())
}

pub fn generate_qr_code(data: &str, output: Option<&Path>) -> Result<(), Box<dyn std::error::Error>> {
    let code = QrCode::new(data)?;
    let image = code.render::<Luma<u8>>().build();
    
    match output {
        Some(path) => {
            image.save(path)?;
            println!("📱 二维码已保存到: {}", path.display());
        },
        None => {
            // 在终端中显示二维码
            let string = code.render()
                .light_color(termcolor::Color::White)
                .dark_color(termcolor::Color::Black)
                .build();
            println!("{}", string);
        }
    }
    
    Ok(())
}

